#include "component.h"
#include "device.h"
#include "msdp.h"
#include "qmc6308.h"

#define MSENSOR_LOG(format, ...) __OSAL_LOG("[msensor.c] " C_BLUE format C_NONE, ##__VA_ARGS__)

#define EVENT_MSENSOR_PROC     0X00000001 /// Msensor处理事件

static FlagStatus msdp_state = SET; /// 伸出锁舌不处理门磁
static Msensor_Action_t publish_status = MSENSOR_STA_INIT; ///上报门当前状态

/**
 * @brief: 获取锁舌是否伸出来
 * @return 
 */
uint8_t Get_MsdpFlag()
{
    return msdp_state;
}

/**
 * @brief: 上报消息给应用层
 * @param {Msensor_enum_t} action 动作
 * @param {uint8_t} res 结果
 * @return {*}
 */
void Msensor_SendMsg(Msensor_enum_t action, uint8_t res)
{
    MSENSOR_LOG("Msensor publish action: %d, res: %d\r\n", action, res);
    MsensorMsg_t msensorMsg;
    msensorMsg.action = action;
    msensorMsg.res = res;
    OSAL_MessagePublish(&msensorMsg, sizeof(msensorMsg));
}

/**
 * @brief: 上报门磁功能开关
 * @param res ENABLE开 DISABLE关
 * @return {*}
 */
void Msensor_SendFuncStatus(FunctionalState res)
{
    Msensor_SendMsg(MSENSOR_FUNC_STATE, (uint8_t)res);
}

/**
 * @brief: 上报门磁校准状态
 * @param res ENABLE开 DISABLE关
 * @return {*}
 */
void Msensor_SendCalStatus(uint8_t res)
{
    Msensor_SendMsg(MSENSOR_CAL_STATE, (uint8_t)res);
}

/**
  * @brief  检测当前门磁位置
  * @note
  *
  * @param  opt：RESET单次检测 SET重复检测
  */
static uint32_t Msensor_CheckDoorStatus(FlagStatus opt)
{
    int16_t xyz[3] = {0};

    if (qmc6308_read_xyz(xyz, opt) == 0)
    {
        MSENSOR_LOG("Msensor data invalid\r\n");
        return 0;
    }

    MsdpEvent_enum_t evt = Msdp_Process(xyz[0], xyz[1], xyz[2]);
    if (evt != MSDP_EVT_NULL)
    {
        if (opt == SET)
        {
            Msensor_Action_t status = (Msensor_Action_t)evt;
            Msensor_SendMsg(MSENSOR_DOOR_STATE, status);
        }
        else
        {
            publish_status = (Msensor_Action_t)evt;
        }
        return 1;
    }
    return 0;
}

#if 0 // test
/**
  * @brief  获取当前门磁数据
  * @note  测试用
  *
  * @param
  */
static uint32_t Msensor_Value(void)
{
    int16_t xyz[3] = {0};

    if (qmc6308_read_xyz(xyz, 0) == 0)
    {
        MSENSOR_LOG("Msensor data invalid\r\n");
        return 0;
    }

    MSENSOR_LOG("Msensor Value  %d  %d  %d\r\n", xyz[0]/2, xyz[1]/2, xyz[2]/2);
    return 0;
}
#endif

static int32_t Msensor_WakeHandle(uint32_t dev)
{
    static uint8_t count = 0;

    //休眠状态下，间隔三个唤醒周期执行一次测量
    if (++count >= 3) // && Get_MsdpFlag())
    {
        count = 0;
        return Msensor_CheckDoorStatus(RESET);
    }
    else
    {
        return 0;
    }
}
COMPONENT_WAKEUP_EXPORT(COMP_MSENSOR, Msensor_WakeHandle, vTIMER_1);

/**
  * @brief  门磁标志位
  * @note 开锁/关锁成功调用
  *
  * @param  opt：RESET锁舌伸出不检测 SET开锁成功检测门磁
  */
static void Set_MsdpFlagApi(FlagStatus state)
{
    msdp_state = state;
    return;
}

/**
 * @brief: 地磁传感器设置接口
 * @param {Msensor_enum_t} param 操作
 * @param {FlagStatus} msg_flag 是否上报消息
 * @return {*}
 */
static ErrorStatus Msensor_SettingApi(Msensor_enum_t param, FlagStatus msg_flag)
{
    static FlagStatus init_flag = RESET;
    uint8_t res;

    if (param == MSENSOR_INIT_LEFT || param == MSENSOR_INIT_RIGHT)
    {
        VirtualHardware_enum_t device = (param == MSENSOR_INIT_LEFT) ? IIC_VHW_MSENSOR_LEFT : IIC_VHW_MSENSOR_RIGHT;

        MSENSOR_LOG("Msensor_init, dir:%s\r\n", (param == MSENSOR_INIT_LEFT) ? "left" : "right");
        if (qmc6308_init(device) == 1)
        {
            init_flag = SET;
            OSAL_EventRepeatCreate(COMP_MSENSOR, EVENT_MSENSOR_PROC, 5, EVT_PRIORITY_LOW);
            MSENSOR_LOG("Msensor_init succeed\r\n");
            return SUCCESS;
        }
        else
        {
            init_flag = RESET;
            MSENSOR_LOG("Msensor_init error\r\n");
            return ERROR;
        }
    }
    else if (param == MSENSOR_SELF_TEST) // 产测测试
    {
        ErrorStatus right_test = ERROR, left_test = ERROR;
        if (Msensor_SettingApi(MSENSOR_INIT_LEFT, RESET) == 1)
        {
            right_test = qmc6308_self_test() == 1 ? SUCCESS : ERROR;
        }
        if (Msensor_SettingApi(MSENSOR_INIT_RIGHT, RESET) == 1)
        {
            left_test = qmc6308_self_test() == 1 ? SUCCESS : ERROR;
        }

        if (init_flag == RESET || (right_test == ERROR && left_test == ERROR))
        {
            res = 0x03; //标记左右门磁检测都失败
        }
        else if (right_test == SUCCESS && left_test == ERROR)
        {
            res = 0x01; //标记左门磁检测失败
        }
        else if (right_test == ERROR && left_test == SUCCESS)
        {
            res = 0x02; //标记右门磁检测失败
        }
        else
        {
            res = 0x00; //左右门磁均检测成功
        }
    }
    else
    {
        MSENSOR_LOG("init_flag : %d\r\n",init_flag);
        if (init_flag == SET)
        {
            MSENSOR_LOG("param : %d\r\n",param);
            if (Msdp_Setting((MsdpSetting_enum_t)param) == 0)
            {
                res = SUCCESS;
            }
            else
            {
                res = ERROR;
            }
        }
        else
        {
            res = ERROR;
        }
    }
    if (msg_flag == SET)
    {
        Msensor_SendMsg(param, res);
    }
    return SUCCESS;
}

/**
 * @brief: 处理邮箱内容
 * @param {uint8_t} *msg
 * @return {*}
 */
static void Msensor_ProcessMbox(uint8_t *msg)
{
    switch (msg[0])
    {
        case MSENSOR_MBOX_SETTING:
            Msensor_SettingApi((Msensor_enum_t)msg[1], (FlagStatus)msg[2]);
            break;
        case MSENSOR_MBOX_SETFLAG:
            Set_MsdpFlagApi((FlagStatus)msg[1]);
            break;
    }
}

/**
  * @brief  地磁传感器任务函数
  *
  * @note
  *         
  * @param  event：当前任务的所有事件
  *
  * @return 返回未处理的事件
  */
static uint32_t Msensor_Task(uint32_t event)
{
	/* 系统启动事件 */
	if (event & EVENT_SYS_START)
	{
		MSENSOR_LOG("Msensor task start\r\n");
        Msdp_Init();
        qmc6308_enable_continue();
        if (publish_status != MSENSOR_STA_INIT)
        {
            Msensor_SendMsg(MSENSOR_DOOR_STATE, publish_status);
            publish_status = MSENSOR_STA_INIT;
        }
        // SYS_API(Msensor_Value);
		return ( event ^ EVENT_SYS_START );
	}

    /* 系统邮箱事件 */
    if (event & EVENT_SYS_MBOX)
    {
        uint8_t buffer[30] = {0};
        while (OSAL_MboxAccept(buffer))
        {
            Msensor_ProcessMbox(buffer);
        }
        return ( event ^ EVENT_SYS_MBOX );
    }
	
	/* 系统休眠事件 */
	if (event & EVENT_SYS_SLEEP)
	{
        int16_t xyz[3] = {0};
        qmc6308_read_xyz(xyz, RESET);
		return ( event ^ EVENT_SYS_SLEEP );
	}

    if (event & EVENT_MSENSOR_PROC)
    {
        Msensor_CheckDoorStatus(SET);
        return ( event ^ EVENT_MSENSOR_PROC );
    }
	
	/* 系统中断事件 */
	if (event & EVENT_SYS_ISR)
	{
		return ( event ^ EVENT_SYS_ISR );
	}
	return 0;
}
COMPONENT_TASK_EXPORT(COMP_MSENSOR, Msensor_Task, 2048);
